#include "keccs_hitTheHay_core_NativeInterface.h"
#include <windows.h>
#include <winuser.h>
#include <powrprof.h>
#include <reason.h>

JNIEXPORT void JNICALL Java_keccs_hitTheHay_core_NativeInterface_hibernate(JNIEnv *env, jclass c) {
	SetSuspendState(1, 1, 0);
}
 
JNIEXPORT void JNICALL Java_keccs_hitTheHay_core_NativeInterface_lockScreen(JNIEnv *env, jclass c) {
	LockWorkStation();
}

JNIEXPORT void JNICALL Java_keccs_hitTheHay_core_NativeInterface_logout(JNIEnv *env, jclass c) {
	ExitWindowsEx(EWX_LOGOFF | EWX_FORCEIFHUNG | EWX_FORCE, 0);
}

JNIEXPORT void JNICALL Java_keccs_hitTheHay_core_NativeInterface_suspend(JNIEnv *env, jclass c) {
	SetSuspendState(0, 1, 0);
}

JNIEXPORT void JNICALL Java_keccs_hitTheHay_core_NativeInterface_monitorOff(JNIEnv *env, jclass c) {
	SendMessageW(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
}

JNIEXPORT void JNICALL Java_keccs_hitTheHay_core_NativeInterface_shutdown(JNIEnv *env, jclass c) {
	ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF | EWX_FORCEIFHUNG | EWX_FORCE, 0);
}

JNIEXPORT jboolean JNICALL Java_keccs_hitTheHay_core_NativeInterface_isSuspendAvailable(JNIEnv *env, jclass c) {
	SYSTEM_POWER_CAPABILITIES cap;
	GetPwrCapabilities(&cap);
	return cap.SystemS3 ? JNI_TRUE : JNI_FALSE;
}

JNIEXPORT jboolean JNICALL Java_keccs_hitTheHay_core_NativeInterface_isHibernateAvailable(JNIEnv *env, jclass c) {
	SYSTEM_POWER_CAPABILITIES cap;
	GetPwrCapabilities(&cap);
	return cap.SystemS4 && cap.HiberFilePresent ? JNI_TRUE : JNI_FALSE;
}

JNIEXPORT jboolean JNICALL Java_keccs_hitTheHay_core_NativeInterface_isShutdownAvailable(JNIEnv *env, jclass c) {
	HANDLE token;
	OpenProcessToken(INVALID_HANDLE_VALUE, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token);
	
	LUID luid;
	LookupPrivilegeValueA(NULL, SE_SHUTDOWN_NAME, &luid);
	
	LUID_AND_ATTRIBUTES lattr;
	lattr.Luid = luid;
	lattr.Attributes = SE_PRIVILEGE_ENABLED;
	
	TOKEN_PRIVILEGES tokenPrivileges;
	tokenPrivileges.PrivilegeCount = 1;
	tokenPrivileges.Privileges[0] = lattr;
	
	BOOL success = AdjustTokenPrivileges(token, FALSE, &tokenPrivileges, 0, NULL, 0);
	return success ? JNI_TRUE : JNI_FALSE;
}






/*
	private static final int EWX_SHUTDOWN = 1;
	private static final int EWX_POWEROFF = 8;
	private static final int EWX_FORCE = 4;
	private static final int EWX_FORCEIFHUNG = 16;

	private static final int TOKEN_ADJUST_PRIVILEGES = 0x20;
	private static final int TOKEN_QUERY = 0x08;

	private static final int SE_PRIVILEGE_ENABLED = 0x02;
	private static final String SE_SHUTDOWN_NAME = "SeShutdownPrivilege";

	private boolean getShutdownPrivileges() {
		Integer token = 0;
		Holder tokenHolder = new Holder(token);
		
		NativeCallHelper.intCall("Advapi32.dll", "OpenProcessToken", -1, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, tokenHolder);
		token = (Integer) tokenHolder.get();
		
		byte[] luid = new byte[8];
		Holder luidHolder = new Holder(luid);
		
		NativeCallHelper.intCall("Advapi32.dll", "LookupPrivilegeValueA", null, SE_SHUTDOWN_NAME, luidHolder);
		luid = (byte[]) luidHolder.get();
				
		byte[] tokenPrivileges = new byte[4 + luid.length + 4];
		
		// set privilegecount
		int priviligeCount = 1;
		tokenPrivileges[0] = (byte)(priviligeCount);
		tokenPrivileges[1] = (byte)(priviligeCount >>> 8);
		tokenPrivileges[2] = (byte)(priviligeCount >>> 16);
		tokenPrivileges[3] = (byte)(priviligeCount >>> 24);
		
		// set LUID
		for (int i = 4; i < 4 + luid.length; i++) {
			tokenPrivileges[i] = luid[i-4];
		}
		
		// set attributes
		tokenPrivileges[4 + luid.length] = (byte)(SE_PRIVILEGE_ENABLED);
		tokenPrivileges[4 + luid.length + 1] = (byte)(SE_PRIVILEGE_ENABLED >>> 8);
		tokenPrivileges[4 + luid.length + 2] = (byte)(SE_PRIVILEGE_ENABLED >>> 16);
		tokenPrivileges[4 + luid.length + 3] = (byte)(SE_PRIVILEGE_ENABLED  >>> 24);
		
		int adjustTokenPrivilegesReturn = NativeCallHelper.intCall("Advapi32.dll", "AdjustTokenPrivileges", token, false, tokenPrivileges, 0, null, 0);
		boolean isSuccessful = (adjustTokenPrivilegesReturn != 0);
		
		return isSuccessful;
	}
	*/
